/* The file is saved in UTF-8 codepage.
 * Check: «Stereotype», Section mark-§, Copyright-©, Alpha-α, Beta-β, Smile-☺
 */
package cz.pecinovsky.english.lootp.utility;

/*******************************************************************************
 *<pre>
 * Předchozí:   Není - toto_je_nově_definovaná_třída
 *              Ttt v projektu Ppp
 * Následující: Prozatím není
 *
 * Projekt  Ppp
 *   + Přidáno
 *   - Odebráno
 *   ~ Změněno
 *</pre>
 */


////////////////////////////////////////////////////////////////////////////////
//%%+  +++++ End of ignored starting test - place for imports +++++


/*******************************************************************************
 * Instance třídy {@code Opakovač} umožňují opakování zadaných akcí
 * na pozadí, tj. be čekání na jejich dokončení.
 *
 * @author Rudolf PECINOVSKÝ
 * @version 6.03.2017 — 2010-11-08
 */
public class Opakovač
{
//== CONSTANT CLASS ATTRIBUTES =================================================

    private static final int POŘÁD = -2;


//== VARIABLE CLASS ATTRIBUTES =================================================
//== CONSTANT INSTANCE ATTRIBUTES ==============================================
//== VARIABLE INSTANCE ATTRIBUTES ==============================================

    /** Opakovač je zrovna zaměstnán. */
    private volatile boolean běží = false;

    /** Byl vydán požadavek k zastavení. */
    private volatile boolean zastavit = false;



//== NESOUKROMÉ METODY TŘÍDY ===================================================
//##############################################################################
//== CONSTUCTORS AND FACTORY METHODS ===========================================
//== ABSTRACT METHODS ==========================================================
//== NESOUKROMÉ  METODY INSTANCÍ ===============================================

    /***************************************************************************
     * Opakuje metodu parametru akce přičemž počet opakování je zadán
     * v parametru počet.
     *
     * @param  počet Požadovaný počet opakování, 0=pořád
     * @param  akce  Instance, jejíž metoda příkaz() bude opakována
     */
    public synchronized void opakuj(final int počet, final IAkční akce)
    {
        if (běží) {
            throw new RuntimeException(
                "\nDokud je opakovač zaměstnán, není možné jej použít");
        }
        běží     = true;
        zastavit = false;
        new Thread(""+akce) {
            int ještě = ((počet == 0) ?  POŘÁD  :  počet);
            @Override
            public void run() {
                do {
                    akce.příkaz();
                }while (! zastavit  &&
                      ((ještě == POŘÁD)  ||  (--ještě > 0)));
                běží = false;
            }
        }.start();
    }


    /***************************************************************************
     * Zastaví opakování prováděná daným opakovačem.
     */
    public synchronized void stop()
    {
        zastavit = true;
    }

//== PRIVATE AND AUXILIARY CLASS METHODS =======================================
//== PRIVATE AND AUXILIARY INSTANCE METHODS ====================================
//== VNOŘENÉ A VNITŘNÍ TŘÍDY ===================================================
//== TESTY =====================================================================
//
//     private static class Čítač implements IAkční {
//         int počet;
//         public void příkaz() {
//             System.out.print(počet++ + ((počet%10==0) ? "\n" : "-"));
//             P.čekej(300);
//         }
//     }
//     /***************************************************************************
//      *
//      */
//     public static void test() {
//         System.out.println("\fSTART");
//         Opakovač o = new Opakovač();
//         Čítač č = new Čítač();
//         o.opakuj(10, č);
//         P.čekej(5000);
//         System.out.println("\nHotovo");
//         č = new Čítač();
//         o.opakuj(0, č);
//         P.zpráva("Ukončit");
//         o.stop();
//         System.out.println("\nKONEC");
//         P.zpráva("Ověř ukončení");
//     }
//
//     public static void main(String... args) { test(); }
}
